今天動手來實作過濾器 Filter 通常用來 format model 的格式,功能上有點類似 computed 因此我們可以利用 Filter 制定系統中常用的 format


import Vue 並使用 filter 來設計,
| 參數一 | 參數二 | 
|---|---|
| filter name | function | 
import Vue from 'vue';
Vue.filter('filterName', function(value) {
  //custom format
  return value.do.some.
});
使用的時候在 bind 的 model 後面使用加上 | 之後再放上 filter name
<p>{{ data | filterName }}</p>
在顯示之前,會透過 filter 過濾格式。
import Vue from 'vue';
Vue.filter('currency', function (num) {
  return '$ ' + num.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, "$1, ");
});
Vue.filter('lowercase', (str) => str.toLowerCase() );
// Letter Grade & GPA
function letterGrade (score) {
  if (score > 100 || score < 0) {
    return '--';
  }
  else if (score >= 90) {
    return 'A';
  }
  else if (score >= 80) {
    return 'B';
  }
  else if (score >= 70) {
    return 'C';
  }
  else if (score >= 60) {
    return 'D';
  }
  else {
    return 'F';
  }
}
Vue.filter('letterGrade', letterGrade);
Vue.filter('gpa', (score) => {
  const _score = letterGrade(score);
  const gpa = {
    A: '4.0',
    B: '3.0',
    C: '2.0',
    D: '1.0',
    F: '0.0',
  }
  return gpa[ _score ] || _score;
});
<template>
  <div class="container">
    <h1>Vue Filter</h1>
    <hr>
    <div class="row">
      <div class="col-md-4">
        <h2>currency:</h2>
        <input type="number" v-model="demoCurrency" />
        <h3>{{ demoCurrency | currency}}</h3> <!-- 過濾貨幣 -->
      </div>
      <div class="col-md-4">
        <h2>lowercase:</h2>
        <input type="text" v-model="demoLowerCase" />
        <h3>{{ demoLowerCase | lowercase}}</h3> <!-- 過濾小寫 -->
      </div>
      <div class="col-md-4">
        <h2>Letter Grade:</h2>
        <input type="number" v-model="demoScore" />
        <h3>{{ demoScore | letterGrade}}
          <small>GPA: ( {{ demoScore | gpa }} )</small><!-- 過濾 GPA -->
        </h3> <!-- 過濾 Letter Grade -->
      </div>
    </div>
   
    <hr>
    <h3>學期分數:</h3>
    <table class="table">
      <thead>
        <tr>
          <th>name</th>
          <th>Letter Grade</th>
          <th>score</th>
          <th>GPA</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in scoreList">
          <td>{{ item.name }}</td>
          <td>{{ item.score | letterGrade}}</td><!-- 過濾 Letter Grade -->
          <td>{{ item.score }}</td>
          <td>{{ item.score | gpa}}</td><!-- 過濾 GPA -->
        </tr>
      </tbody>
    </table>
  </div>
</template>
<script>
export default {
  data() {
    return {
      demoCurrency: 1000,
      demoLowerCase: 'LOWER CASE',
      demoScore: 99,
      scoreList: [
        {name: 'jacky', score: 100},
        {name: 'momo', score: 90},
        {name: 'jasper', score: 89},
        {name: 'eason', score: 80},
        {name: 'mars', score: 79},
        {name: 'mike', score: 70},
        {name: 'ben', score: 69},
        {name: 'Aaron', score: 60},
        {name: 'mary', score: 59},
      ],
    };
  },
};
</script>
在 Vue 1.x 的時候其實官方有制定許多個 filter 供開發者使用,
到了 Vue 2.x 官方移除了這些 filter 種種原因在這篇討論中:
[Suggestion] Vue 2.0 - Bring back filters please #2756
{{ data | filter1:data2 | filter2 | filter3 | WTF }}
angular 時代真的很容易也很愛開發那種 filter..
後面維護的同事看了表示香菇..debug 看過.. 改一個 model 然後 filter 算了 30000 次..
看完了 filter 的優缺點,目前使用上不多,
大部分都是像範例上這種簡單,不複雜計算的格式轉換,
這些格式轉換往往是需求的關係,所以在最後顯示之前過濾成需求的格式既可。
不會動到後端原始資料,設定的時候也不需要轉回原本格式,相當方便。
另外就是因為使用了 vuex 在有些狀況可以寫好 format function 如範例中: letterGrade
我們在 getter 的時候.. 先經過 letterGrade 過濾在把資料回傳,
因此 UI 就不用煩惱要在哪個流程 format,取得資料的時候就過濾好囉。
filter,getter共用一個函式統一維護。
實作小範例入門 Vue & Vuex 2.0 - github 完整範例
使用 git checkout 切換每天範例。